import RPi.GPIO as GPIO
import smbus
import logging
import time
import subprocess
from config import load_config

# 检测树莓派型号
def get_raspberry_pi_model():
    try:
        with open('/proc/cpuinfo', 'r') as f:
            cpuinfo = f.read()
        if 'BCM2712' in cpuinfo:
            return 'pi5'
        elif 'BCM2835' in cpuinfo or 'BCM2711' in cpuinfo:
            return 'pi4'
        else:
            return 'unknown'
    except Exception as e:
        logger.error(f"无法检测树莓派型号: {e}")
        return 'unknown'

# 初始化时检查树莓派型号
raspberry_pi_model = get_raspberry_pi_model()
if raspberry_pi_model not in ['pi4', 'pi5']:
    logger.error(f"不支持的树莓派型号: {raspberry_pi_model}，程序仅支持树莓派4/5")
    raise RuntimeError("不支持的硬件平台")

# 配置日志
logger = logging.getLogger(__name__)

# 引脚定义
FLAME_PIN = 17
SMOKE_PIN = 27
BUZZER_PIN = 22
OLED_ADDR = 0x3C
RESET_BUTTON_PIN = 23
GREEN_LED_PIN = 24
RED_LED_PIN = 25
RESET_PIN = 26  # OLED复位引脚

# 全局变量
buzzer = None
i2c_bus = None
dht_data = {'temperature': 0, 'humidity': 0}
hardware_info = {'cpu_usage': 0, 'cpu_temp': 0, 'mem_usage': 0}
error_count = 0
error_types = {}

def init_gpio():
    """初始化GPIO引脚，返回初始化结果"""
    try:
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(FLAME_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(SMOKE_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(BUZZER_PIN, GPIO.OUT)
        GPIO.setup(RESET_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(GREEN_LED_PIN, GPIO.OUT)
        GPIO.setup(RED_LED_PIN, GPIO.OUT)
        GPIO.setup(RESET_PIN, GPIO.OUT)
        # RTC电池充电控制引脚
        GPIO.setup(RTC_BATTERY_CHARGE_PIN, GPIO.OUT)
        GPIO.output(RTC_BATTERY_CHARGE_PIN, GPIO.LOW)  # 初始不充电
        # 初始状态：绿灯亮，红灯灭
        GPIO.output(GREEN_LED_PIN, GPIO.HIGH)
        GPIO.output(RED_LED_PIN, GPIO.LOW)
        global buzzer
        buzzer = GPIO.PWM(BUZZER_PIN, 1000)
        logger.info("GPIO初始化成功")
        return True
    except Exception as e:
        logger.error(f"GPIO初始化失败: {e}")
        return False

def init_i2c():
    """初始化I2C总线"""
    global i2c_bus
    try:
        i2c_bus = smbus.SMBus(1)  # 树莓派通常使用I2C总线1
        return True
    except Exception as e:
        logger.error(f"I2C初始化失败: {e}")
        return False

def scan_i2c_devices():
    """扫描I2C设备"""
    devices = []
    if i2c_bus is None:
        return devices
    try:
        for addr in i2c_bus.scan():
            devices.append(addr)
        return devices
    except Exception as e:
        logger.error(f"I2C扫描失败: {e}")
        return []

def detect_clock_chip():
    """检测时钟芯片"""
    devices = scan_i2c_devices()
    # 转换为十六进制地址以便比较
    hex_devices = [hex(addr) for addr in devices]
    if '0x68' in hex_devices or '0x51' in hex_devices:
        return 'ds3231' if '0x68' in hex_devices else 'pcf8563'
    return ''

# 传感器检测计数器
flame_counter = 0
smoke_counter = 0

# 传感器故障检测
flame_failure_count = 0
smoke_failure_count = 0
oled_failure_count = 0
led_failure_count = 0
rtc_battery_failure_count = 0
FAILURE_THRESHOLD = 5  # 连续失败次数阈值

# RTC芯片配置
RTC_CONFIG = {
    'pi5': {'chip': 'da9091', 'i2c_addr': 0x68, 'battery_reg': 0x0F, 'charge_reg': 0x10},
    'pi4': {'chip': 'pcf8563', 'i2c_addr': 0x51, 'battery_reg': 0x02, 'charge_reg': None}
}

# RTC电池配置
RTC_BATTERY_CHARGE_PIN = 18  # 充电控制引脚
RTC_BATTERY_LOW_THRESHOLD = 20  # 低电量阈值(%)

# 从配置读取电池类型
config = load_config()
RTC_BATTERY_TYPE = config.get('RTC', 'battery_type', fallback='rechargeable')

sensor_status = {
    'flame': 'normal',
    'smoke': 'normal',
    'oled': 'normal',
    'green_led': 'normal',
    'red_led': 'normal',
    'rtc_battery': 'normal'
}

def detect_oled_status():
    """检测OLED是否正常工作"""
    global oled_failure_count, sensor_status, i2c_bus
    try:
        if i2c_bus is None:
            logger.error("I2C总线未初始化，无法检测OLED状态")
            return False
        # 尝试初始化OLED
        from ssd1306 import SSD1306_I2C
        oled = SSD1306_I2C(128, 64, i2c_bus, addr=OLED_ADDR)
        oled.text('Test', 0, 0)
        oled.show()
        oled_failure_count = 0
        sensor_status['oled'] = 'normal'
        return True
    except Exception as e:
        oled_failure_count += 1
        if oled_failure_count >= FAILURE_THRESHOLD:
            sensor_status['oled'] = 'failure'
            logger.error(f"OLED显示故障: {e}")
        return False

def detect_led_status():
    """检测LED是否正常工作"""
    global led_failure_count, sensor_status
    try:
        # 测试绿灯
        GPIO.output(GREEN_LED_PIN, GPIO.LOW)
        time.sleep(0.1)
        GPIO.output(GREEN_LED_PIN, GPIO.HIGH)
        
        # 测试红灯
        GPIO.output(RED_LED_PIN, GPIO.LOW)
        time.sleep(0.1)
        GPIO.output(RED_LED_PIN, GPIO.HIGH)
        
        led_failure_count = 0
        sensor_status['green_led'] = 'normal'
        sensor_status['red_led'] = 'normal'
        return True
    except Exception as e:
        led_failure_count += 1
        if led_failure_count >= FAILURE_THRESHOLD:
            sensor_status['green_led'] = 'failure'
            sensor_status['red_led'] = 'failure'
            logger.error(f"LED故障: {e}")
        return False

def read_rtc_battery_level():
    """读取RTC电池电量，返回百分比或-1表示读取失败"""
    try:
        if i2c_bus is None:
            init_i2c()
        
        # 获取当前RTC配置
        rtc_config = RTC_CONFIG.get(raspberry_pi_model, RTC_CONFIG['pi4'])
        
        # 读取电池状态寄存器
        status_reg = i2c_bus.read_byte_data(rtc_config['i2c_addr'], rtc_config['battery_reg'])
        
        # 根据不同芯片解析电池状态
        if rtc_config['chip'] == 'da9091':
            # DA9091: 假设BIT6表示低电量
            battery_low = (status_reg & 0x40) != 0
        else:  # pcf8563/ds3231
            # PCF8563: BIT7表示电池低电量
            battery_low = (status_reg & 0x80) != 0
        
        # 模拟电量百分比（实际应根据电压检测）
        return 10 if battery_low else 80
    except Exception as e:
        logger.error(f"读取RTC电池状态失败: {e}")
        return -1

def detect_rtc_battery_status():
    """检测RTC电池状态，处理充电逻辑"""
    global rtc_battery_failure_count, sensor_status
    config = load_config()
    
    try:
        # 从配置读取电池类型
        battery_type = config.get('RTC', 'battery_type', fallback='rechargeable')
        
        battery_level = read_rtc_battery_level()
        if battery_level == -1:
            rtc_battery_failure_count += 1
            if rtc_battery_failure_count >= FAILURE_THRESHOLD:
                sensor_status['rtc_battery'] = 'failure'
                logger.error("RTC电池检测故障")
            return False
        
        # 重置故障计数
        rtc_battery_failure_count = 0
        
        # 获取当前RTC配置
        rtc_config = RTC_CONFIG.get(raspberry_pi_model, RTC_CONFIG['pi4'])
        
        # 处理可充电电池
        if battery_type == 'rechargeable':
            if battery_level <= RTC_BATTERY_LOW_THRESHOLD:
                # 开启充电（根据不同芯片选择控制方式）
                if rtc_config['chip'] == 'da9091' and rtc_config['charge_reg'] is not None:
                    # DA9091通过I2C寄存器控制充电
                    i2c_bus.write_byte_data(rtc_config['i2c_addr'], rtc_config['charge_reg'], 0x01)
                else:
                    # 其他情况通过GPIO控制
                    GPIO.output(RTC_BATTERY_CHARGE_PIN, GPIO.HIGH)
                sensor_status['rtc_battery'] = 'charging'
                logger.info(f"RTC电池电量低({battery_level}%)，开始充电")
            else:
                # 关闭充电
                if rtc_config['chip'] == 'da9091' and rtc_config['charge_reg'] is not None:
                    i2c_bus.write_byte_data(rtc_config['i2c_addr'], rtc_config['charge_reg'], 0x00)
                else:
                    GPIO.output(RTC_BATTERY_CHARGE_PIN, GPIO.LOW)
                sensor_status['rtc_battery'] = 'normal'
        else:
            # 处理非充电电池
            if battery_level <= RTC_BATTERY_LOW_THRESHOLD:
                sensor_status['rtc_battery'] = 'failure'
                logger.warning(f"RTC电池电量低({battery_level}%)，请更换电池")
            else:
                sensor_status['rtc_battery'] = 'normal'
        
        return True
    except Exception as e:
        logger.error(f"RTC电池检测错误: {e}")
        rtc_battery_failure_count += 1
        if rtc_battery_failure_count >= FAILURE_THRESHOLD:
            sensor_status['rtc_battery'] = 'failure'
        return False

def check_sensors():
    """检查传感器状态，支持阈值判断和故障检测，增加防误报逻辑"""
    global flame_counter, smoke_counter, flame_failure_count, smoke_failure_count
    config = load_config()
    
    # 获取配置阈值
    flame_threshold = config.getint('SENSORS', 'flame_threshold', fallback=3)
    smoke_threshold = config.getint('SENSORS', 'smoke_threshold', fallback=3)
    sample_interval = config.getfloat('SENSORS', 'sample_interval', fallback=0.1)
    
    # 多次采样确认
    flame_samples = []
    smoke_samples = []
    for _ in range(5):
        try:
            flame_value = GPIO.input(FLAME_PIN)
            smoke_value = GPIO.input(SMOKE_PIN)
            flame_samples.append(flame_value == GPIO.LOW)
            smoke_samples.append(smoke_value == GPIO.LOW)
            time.sleep(sample_interval)
        except Exception as e:
            logger.error(f"传感器采样失败: {e}")
            return False, None
    
    # 多数表决确认
    flame_detected = sum(flame_samples) >= 3
    smoke_detected = sum(smoke_samples) >= 3
    
    # 火焰传感器故障检测
    if len(set(flame_samples)) == 1 and flame_threshold > 0:
        flame_failure_count += 1
    else:
        flame_failure_count = 0
        
    if flame_failure_count >= FAILURE_THRESHOLD:
        sensor_status['flame'] = 'failure'
        logger.error("火焰传感器故障: 读数异常")
    else:
        sensor_status['flame'] = 'normal'
    
    # 烟雾传感器故障检测
    if smoke_value not in [GPIO.HIGH, GPIO.LOW]:
        smoke_failure_count += 1
    else:
        smoke_failure_count = 0
        
    if smoke_failure_count >= FAILURE_THRESHOLD:
        sensor_status['smoke'] = 'failure'
        logger.error("烟雾传感器故障: 读数异常")
    else:
        sensor_status['smoke'] = 'normal'
    
    # 火焰检测（累计达到阈值才触发）
    if flame_detected and sensor_status['flame'] == 'normal':
        flame_counter += 1
        if flame_counter >= flame_threshold:
            logger.warning(f"火焰检测到! (连续{flame_counter}次)")
            flame_counter = 0  # 重置计数器
            return True, "flame"
    else:
        flame_counter = 0  # 未检测到则重置计数器
    
    # 烟雾检测（累计达到阈值才触发）
    if smoke_detected and sensor_status['smoke'] == 'normal':
        smoke_counter += 1
        if smoke_counter >= smoke_threshold:
            logger.warning(f"烟雾检测到! (连续{smoke_counter}次)")
            smoke_counter = 0  # 重置计数器
            return True, "smoke"
    else:
        smoke_counter = 0  # 未检测到则重置计数器
    
    return False, None

def reset_sensors():
    """重置传感器数据和硬件"""
    global dht_data, hardware_info, error_count, error_types, flame_counter, smoke_counter
    
    try:
        # 重置传感器数据
        dht_data = {'temperature': 0, 'humidity': 0}
        hardware_info = {'cpu_usage': 0, 'cpu_temp': 0, 'mem_usage': 0}
        error_count = 0
        error_types = {}
        flame_counter = 0
        smoke_counter = 0
        
        # 清理并重新初始化传感器
        GPIO.cleanup()
        gpio_success = init_gpio()
        i2c_success = init_i2c()
        
        if gpio_success and i2c_success:
            logger.info("传感器已手动/自动复位")
            return True
        else:
            logger.error("传感器复位失败: GPIO或I2C初始化错误")
            return False
    except Exception as e:
        logger.error(f"传感器复位过程出错: {e}")
        return False

def manual_reset_sensors():
    """手动触发传感器复位"""
    logger.info("用户触发手动传感器复位")
    return reset_sensors()